<template>
	<div
		v-if="contextMenu.visible"
		ref="floatingMenu"
		:style="floatingMenuStyle"
		class="custom-context-menu"
	>
		<div v-if="contextMenu.type === 'group'">
			<div class="menu-item" @click="handleContextMenuCommand('lock'); closeContextMenu()">
				<i class="iconfont">{{ contextMenu.node.raw.locked ? '&#xe6a9;':'&#xe6aa;' }}</i>
				{{ contextMenu.node.raw.locked ? '解锁分组' : '锁定分组' }}
			</div>
			<div class="menu-item" @click="handleContextMenuCommand('rename'); closeContextMenu()">
				<i class="iconfont">&#xe6a1;</i> 重命名
			</div>
			<div class="menu-item" @click="handleContextMenuCommand('ungroup'); closeContextMenu()">
				<i class="iconfont">&#xe62a;</i> 解散分组 
			</div>
			<div class="menu-divider"></div>
			<div class="menu-item" @click="handleContextMenuCommand('front'); closeContextMenu()">
				<i class="iconfont">&#xe63e;</i> 分组置顶
			</div>
			<div class="menu-item" @click="handleContextMenuCommand('back'); closeContextMenu()">
				<i class="iconfont">&#xe63f;</i> 分组置底
			</div>
			<div class="menu-item" @click="handleContextMenuCommand('up'); closeContextMenu()">
				<i class="iconfont">&#xe66e;</i> 分组上移一层
			</div>
			<div class="menu-item" @click="handleContextMenuCommand('down'); closeContextMenu()">
				<i class="iconfont">&#xe66d;</i> 分组下移一层
			</div>
			
			<div class="menu-item" @click="handleContextMenuCommand('visible'); closeContextMenu()">
				<i class="iconfont">{{ contextMenu.node.raw.visible ? '&#xe640;' : '&#xeb46;' }}</i>
				{{ contextMenu.node.raw.visible ? '隐藏分组' : '显示分组' }}
			</div>
			<div class="menu-divider"></div>
			
			<div class="menu-item" @click="handleContextMenuCommand('addComponent'); closeContextMenu()">
				<i class="iconfont">&#xe610;</i> 添加组元素
			</div>
			
			<div class="menu-item" @click="handleContextMenuCommand('copy'); closeContextMenu()">
				<i class="iconfont">&#xe61d;</i> 复制分组
			</div>
			<div class="menu-item" @click="handleContextMenuCommand('delete'); closeContextMenu()">
				<i class="iconfont">&#xe600;</i> 删除分组
			</div>
		</div>	
		<div v-else>
			<div class="menu-item" @click="handleContextMenuCommand('lock'); closeContextMenu()">
				<i class="iconfont">{{ contextMenu.node.raw.locked  ? '&#xe6a9;':'&#xe6aa;'  }}</i>
				{{ contextMenu.node.raw.locked  ? '解锁' : '锁定' }}
			</div>
			<div class="menu-divider"></div>
			<div class="menu-item" @click="handleContextMenuCommand('front'); closeContextMenu()">
			  <i class="iconfont">&#xe63e;</i> 置顶 (Ctrl+Shift+↑)
			</div>
			<div class="menu-item" @click="handleContextMenuCommand('back'); closeContextMenu()">
			  <i class="iconfont">&#xe63f;</i> 置底 (Ctrl+Shift+↓)
			</div>
			<div class="menu-item" @click="handleContextMenuCommand('up'); closeContextMenu()">
			  <i class="iconfont">&#xe66e;</i> 上移一层 (Ctrl+↑)
			  </div>
			<div class="menu-item" @click="handleContextMenuCommand('down'); closeContextMenu()">
			  <i class="iconfont">&#xe66d;</i> 下移一层 (Ctrl+↓)
			</div>
			
			<div class="menu-item" @click="handleContextMenuCommand('visible'); closeContextMenu()">
				<i class="iconfont">{{ contextMenu.node.raw.visible ? '&#xe640;' : '&#xeb46;' }}</i>
				{{ contextMenu.node.raw.visible ? '隐藏' : '显示' }}
			</div>
			
			<div class="menu-divider"></div>
			<div class="menu-item" @click="handleContextMenuCommand('selectAll'); closeContextMenu()" v-if="dynamicVisualStore.currentComponents.length > 0">
			  <i class="iconfont">&#xe8ed;</i> 全选 (Ctrl+A)
			</div>
			
			<div class="menu-item" @click="handleContextMenuCommand('removeComponent'); closeContextMenu()" v-if="contextMenu.node.raw.isGrouped ">
			  <i class="iconfont">&#xe634;</i> 移除所在组
			</div>
			
			<div class="menu-divider"></div>
			<div class="menu-item" @click="handleContextMenuCommand('delete'); closeContextMenu()">
			  <i class="iconfont">&#xe600;</i> 删除 (Delete)
			</div>
			<div class="menu-item" @click="handleContextMenuCommand('copy'); closeContextMenu()" >
			  <i class="iconfont">&#xe61d;</i> 复制
			</div>
		</div>
		
		
		<!--分组中添加组件-->
		<el-dialog
		    v-model="addComponentDialogVisible"
		    :title="addComponentDialogTitle"
		    width="500"
		  >
			<div>
				
		    <el-scrollbar height="calc(100%)">
		      <el-tree
			    ref="addComponentDialogTreeRef"
		        :data="structureTree"
		        :props="addComponentTreeProps"
		        node-key="id"
		        highlight-current
		        default-expand-all
				:show-checkbox="true"
				:check-on-click-node="true"
				:check-strictly="true"
				:check-on-click-leaf="true"
		        style="background:transparent;"
		      >
		        <template #default="{ data }">
		          <span>
		            {{ data.label }}
		          </span>
		        </template>
		      </el-tree>
		      </el-scrollbar>
				
			</div>
		  
		    <template #footer>
		      <div class="dialog-footer">
		        <el-button @click="closeAddComponentDialog">取消</el-button>
		        <el-button type="primary" @click="confirmAddComponent">
		          确定
		        </el-button>
		      </div>
		    </template>
		</el-dialog>
	</div>
</template>

<script setup lang="ts">
import { ElMessageBox ,ElMessage} from 'element-plus'
import { ref, watch, computed, nextTick,CSSProperties } from 'vue'
import type { PageFilter, PropertiesPanelProps, ComponentInstance, ComponentGroup } from '@/types/visual-app'
import { computePosition, offset, flip, shift, autoUpdate } from '@floating-ui/dom'
import { useVisualStore } from '@/store/visual'
const dynamicVisualStore = useVisualStore()
const emit = defineEmits([
	'update:pageTitle',
	'update:pageSize',
	'update:pageBgColor',
	'update:pageBgImg',
	'update:fitMode',
	'update:filter',
	'update:themeColor',
	'update:pageBindings',
	'selectComponentById',
	'selectGroupById',
	'update:groupBindings',
	'structureContextMenu',
])


// 结构树属性
const treeProps = { label: 'label', children: 'children' }
// 生成页面结构树
const structureTree = computed(() => {
  // 先分组，再组件
  const groupMap: Record<string, any> = {}
  if (Array.isArray( dynamicVisualStore.currentGroups())) {
     dynamicVisualStore.currentGroups().forEach((g: any) => {
      groupMap[g.id] = {
        id: g.id,
        label: g.name,
        type: 'group',
        children: [],
		raw: g
      }
    })
  } 
  const nodes: any[] = []
  if (Array.isArray(dynamicVisualStore.currentComponents())) {
    dynamicVisualStore.currentComponents().forEach((c: any) => {
      if (c.groupId && groupMap[c.groupId]) {
        groupMap[c.groupId].children.push({
          id: c.id,
          label: c.title || c.type,
          type: 'component',
		  componentId: c.componentId,
          raw: c
        })
      } else {
        nodes.push({
          id: c.id,
          label: c.title || c.type,
          type: 'component',
		  componentId: c.componentId,
          raw: c
        })
      }
    })
  }
  // 分组节点放前面
  return [
    ...Object.values(groupMap),
    ...nodes
  ]
})
	
	
const contextMenu = ref({
  visible: false,
  x: 0,
  y: 0,
  node: null as any,
  type: '' as 'component' | 'group' | ''
})

const closeContextMenu=()=> {
  contextMenu.value.visible = false
  contextMenu.value.node = null
  contextMenu.value.type = ''
  if (cleanupFloating) {
    cleanupFloating()
    cleanupFloating = null
  }
  document.removeEventListener('click', closeContextMenu)
}

const handleContextMenuCommand=(command: string)=> {
  if (!contextMenu.value.node) return
  if('addComponent'==command){
		addComponentDialog(contextMenu.value.node.id,contextMenu.value.node.label,contextMenu.value.node.raw.componentIds)
  }
  else if('removeComponent'==command){
		removeComponentFormGroup(contextMenu.value.node.id,contextMenu.value.node.raw.groupId,contextMenu.value.node.label)  
  }
  else{
		emit('structureContextMenu', { command, node: contextMenu.value.node })
		closeContextMenu()
  }
}	

const addComponentDialogTreeRef=ref();
const addComponentDialogVisible=ref<boolean>(false);
const addComponentDialogTitle=ref<string>('');
const currentHasComponentIds=ref<string[]>([])
const addComponentToGroupId=ref<string>('');
const addComponentTreeProps = {
  children: 'children',
  label: 'name',
  disabled: (data:any) => {
		return (data.children && data.children.length > 0) || currentHasComponentIds.value.includes(data.id);
  },
};

const addComponentDialog=(nodeId:string,label:string,children:string[])=>{
	addComponentToGroupId.value=nodeId;
	addComponentDialogTitle.value=label
	currentHasComponentIds.value=children;
	addComponentDialogVisible.value=true;
}

const confirmAddComponent=()=>{
	const keys=addComponentDialogTreeRef.value.getCheckedKeys();
	if(keys.length>0){
		ElMessageBox.confirm('确定向【'+addComponentDialogTitle.value+'】添加【'+keys.length+'】个组件吗？', '添加组件确认', {
			confirmButtonText: '确定',
			cancelButtonText: '取消',
			type: 'warning'
		}).then(async () => {
			try {
				dynamicVisualStore.addComponentToGroup(addComponentToGroupId.value,keys)
				ElMessage.success('添加成功')
			} catch {
				ElMessage.error(`添加失败`)
			}finally{
				closeAddComponentDialog()
			}
		})
	}else{
		closeAddComponentDialog()
	}
}

const removeComponentFormGroup=(componentId:string,groupId:string,label:string)=>{
	ElMessageBox.confirm('确定将组件【'+label+'】移除分组吗？', '移除组件确认', {
		confirmButtonText: '确定',
		cancelButtonText: '取消',
		type: 'warning'
	}).then(async () => {
		try {
			dynamicVisualStore.removeComponentFromGroup(componentId,groupId)
			ElMessage.success('添加成功')
		} catch {
			ElMessage.error(`添加失败`)
		}finally{
			closeAddComponentDialog()
		}
	})
}

const closeAddComponentDialog=()=>{
	addComponentDialogVisible.value=false;
	addComponentDialogTitle.value='';
	addComponentToGroupId.value='';
	currentHasComponentIds.value=[]
}


// --- floating-ui 相关变量 ---
const floatingMenu = ref<HTMLElement | null>(null)
const floatingMenuStyle = ref({ 
  left: '0px', 
  top: '0px', 
  position: 'fixed' as const, 
  zIndex: 9999 
})

// const contextMenuStyle = computed(() => ({
//   position: 'fixed' as CSSProperties['position'],
//   left: contextMenu.value.x + 'px',
//   top: contextMenu.value.y + 'px',
//   zIndex: 9999
// }))



let cleanupFloating: any = null


const handleNodeContextMenu=(event: MouseEvent, data: any, _node: any)=> {
	if(dynamicVisualStore.debugMode==true) return;
	event.preventDefault()
	contextMenu.value.visible = false
	contextMenu.value.x = event.clientX
	contextMenu.value.y = event.clientY
	contextMenu.value.node = data
	contextMenu.value.type = data.type
	
	if(data.type=='group'){
		 emit('selectGroupById', data.id.replace('group-', ''))
	}
	else if(data.type=='component'){
		emit('selectComponentById', data.raw.id)
	}
	
	nextTick(() => {
		contextMenu.value.visible = true
		nextTick(() => {
			if (floatingMenu.value) {
				if (cleanupFloating) cleanupFloating()
				cleanupFloating = autoUpdate(
				  { getBoundingClientRect: () => ({ x: contextMenu.value.x, y: contextMenu.value.y, width: 0, height: 0, top: contextMenu.value.y, left: contextMenu.value.x, right: contextMenu.value.x, bottom: contextMenu.value.y }) },
				  floatingMenu.value,
				  () => {
					if (floatingMenu.value) {
					  computePosition(
						{ getBoundingClientRect: () => ({ x: contextMenu.value.x, y: contextMenu.value.y, width: 0, height: 0, top: contextMenu.value.y, left: contextMenu.value.x, right: contextMenu.value.x, bottom: contextMenu.value.y }) },
						floatingMenu.value,
						{
						  strategy: 'fixed',
						  placement: 'right-start',
						  middleware: [offset(4), flip(), shift()]
						}
					  ).then(({ x, y }: { x: number; y: number }) => {
						floatingMenuStyle.value = {
						  left: `${x}px`,
						  top: `${y}px`,
						  position: 'fixed',
						  zIndex: 9999
						}
					  })
					}
				  }
				)
			}
		});
	})
	document.addEventListener('click', closeContextMenu)
}



defineExpose({
  handleNodeContextMenu,
})
	
</script>

<style scoped>
	.custom-context-menu {
		position: fixed;
		background-color: var(--art-main-bg-color);
		border: 1px solid var(--art-card-border);
		border-radius: 4px;
		box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
		z-index: 9999;
		min-width: 160px;
		padding: 5px 0;
		font-size: 14px;
		color: #606266;
	  
		.menu-item {
			padding: 8px 16px;
			cursor: pointer;
			display: flex;
			align-items: center;
			transition: background-color 0.2s;
			color: var(--art-gray-700);
			
			&:hover {
			  background-color: rgba(var(--art-gray-300-rgb), 0.75);
			  color: var(--art-gray-800);
			  
			  i {
			    color: var(--art-gray-800);
			  }
			}
			
			i {
				margin-right: 8px;
				font-size: 14px;
				width: 16px;
				color: var(--art-gray-700);
				text-align: center;
			}
		}
	  
		.menu-divider {
			height: 1px;
			background-color:var(--art-card-border); 
			margin: 5px 0;
		}
	}
</style>